using LightCAD.MathLib;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;


namespace LightCAD.Three
{
    public class LoadingManager
    {
        public static readonly LoadingManager DefaultLoadingManager = new LoadingManager();

        #region scope properties or methods
        #endregion

        #region Properties
        public Action<string, int, int> onStart;
        public Action onLoad;
        public Action<string> onProgress;
        public Action<string> onError;
        private Func<string, string> urlModifier;
        private LoadingManager scope;
        private bool isLoading = false;
        private int itemsLoaded = 0;
        private int itemsTotal = 0;
        public ListEx<object> handlers;
        #endregion

        #region constructor
        public LoadingManager(Action onLoad = null, Action<string> onProgress = null, Action<string> onError = null)
        {
            this.scope = this;
            this.isLoading = false;
            this.itemsLoaded = 0;
            this.itemsTotal = 0;
            this.urlModifier = null;
            var handlers = new ListEx<object>();
            // Refer to #5689 for the reason why we don"t set .onStart
            // in the constructor
            this.onStart = null;
            this.onLoad = onLoad;
            this.onProgress = onProgress;
            this.onError = onError;

        }
        public void itemStart(string url)
        {
            itemsTotal++;
            if (isLoading == false)
            {
                if (scope.onStart != null)
                {
                    scope.onStart(url, itemsLoaded, itemsTotal);
                }
            }
            isLoading = true;
        }
        public void itemEnd(string url)
        {
            itemsLoaded++;
            if (scope.onProgress != null)
            {
                scope.onProgress(url);
            }
            if (itemsLoaded == itemsTotal)
            {
                isLoading = false;
                if (scope.onLoad != null)
                {
                    scope.onLoad();
                }
            }
        }
        public void itemError(string url)
        {
            if (scope.onError != null)
            {
                scope.onError(url);
            }
        }
        public string resolveURL(string url)
        {
            return urlModifier?.Invoke(url) ?? url;
        }
        public LoadingManager setURLModifier(Func<string, string> transform)
        {
            urlModifier = transform;
            return this;
        }
        public LoadingManager addHandler(Regex regex, Loader<object> loader)
        {
            handlers.Push(regex, loader);
            return this;
        }
        public LoadingManager removeHandler(Regex regex)
        {
            var index = handlers.IndexOf(regex);
            if (index != -1)
            {
                handlers.Splice(index, 2);
            }
            return this;
        }
        public object getHandler(string file)
        {
            for (int i = 0, l = handlers.Length; i < l; i += 2)
            {
                var regex = handlers[i] as Regex;
                var loader = handlers[i + 1];
                //if (regex.Options==RegexOptions.gloa) regex.lastIndex = 0; // see #17920
                if (regex.IsMatch(file))
                {
                    return loader;
                }
            }
            return null;
        }
        #endregion

    }
}
